package com.devframe.web.struts2.result;


import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;


import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.ServletDispatcherResult;
import org.apache.struts2.views.util.DefaultUrlHelper;
import org.apache.struts2.views.util.UrlHelper;

import com.devframe.web.MyAction;
import com.devframe.web.MyContext;
import com.devframe.web.MyStatics;
import com.devframe.web.Struts2BaseAction;
import com.devframe.web.WebContext;
import com.devframe.web.handle.ExportXlsResultHandle;
import com.devframe.web.handle.JSONResultHandle;
import com.devframe.web.interceptors.MyInterceptorStack;
import com.devframe.web.util.common.PagePathUtils;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;

import static javax.servlet.http.HttpServletResponse.SC_FOUND;
/**
 * 
 * @author 詹保山
 * @desc: 进行多功能的页面派遣操作
 * 
 */
public class MyActionResult extends ServletDispatcherResult {
	private static final Logger LOG = LoggerFactory.getLogger(MyActionResult.class);
    protected int statusCode = SC_FOUND;
    private UrlHelper urlHelper=new DefaultUrlHelper();
    private JSONResultHandle jsonResult;
    private ExportXlsResultHandle exportXlsResult;

    private MyContext getContext(ActionInvocation invocation){
    	if(invocation.getAction() instanceof Struts2BaseAction){
    		return ((Struts2BaseAction)invocation.getAction()).getContext();
    	}else{
    		return new WebContext(ServletActionContext.getRequest());
    	}
    }
	
    protected List<String> getProhibitedResultParams() {
        return Arrays.asList(new String[]{
                DEFAULT_PARAM, "namespace", "method", "encode", "parse", "location",
                "prependServletContext", "supressEmptyParameters"});
    }
    protected void sendRedirect(HttpServletResponse response, String finalLocation) throws IOException {
        if (SC_FOUND == statusCode) {
            response.sendRedirect(finalLocation);
        } else {
            response.setStatus(statusCode);
            response.setHeader("Location", finalLocation);
            response.getWriter().write(finalLocation);
            response.getWriter().close();
        }
    }
	private void doRedirectExecute(String finalLocation, ActionInvocation invocation) throws Exception{
		Map<String,Object> requestParameters = new LinkedHashMap<String,Object>();
        Map resultConfigParams = ServletActionContext.getRequest().getParameterMap();
        for (Iterator i = resultConfigParams.entrySet().iterator(); i.hasNext();) {
            Map.Entry e = (Map.Entry) i.next();
            if (!getProhibitedResultParams().contains(e.getKey())) {
                String potentialValue = e.getValue() == null ? "" : conditionalParse(e.getValue().toString(), invocation);
                if (((potentialValue != null) && (potentialValue.length() > 0))) {
                    requestParameters.put(e.getKey().toString(), potentialValue);
                }
            }
        }
        StringBuilder tmpLocation = new StringBuilder(finalLocation);
        urlHelper.buildParametersString(requestParameters, tmpLocation, "&");
        finalLocation = ServletActionContext.getResponse().encodeRedirectURL(tmpLocation.toString());
	    if (LOG.isDebugEnabled()) {
	        LOG.debug("跳转地址=" + finalLocation);
	    }
       sendRedirect(ServletActionContext.getResponse(), finalLocation);
	}
	
	private void exportExcel(MyContext context, Object data, HttpServletResponse response, String templateFileName){
		if(exportXlsResult==null){
			exportXlsResult=new ExportXlsResultHandle();
		}
		 LOG.info("导出EXCEL文件");
		 exportXlsResult.execute(context, response, data, templateFileName);
	}
	
	
	/**
	 * 异步结果输出
	 * @param finalLocation
	 * @param invocation
	 * @author:詹保山
	 */
    
	private void doAjaxExecute(String finalLocation,ActionInvocation invocation){
		
        // 判断是否为导出，对应AJAX的导出请求，必须有exportToExcel=true,此时将返回值传递给模板
        // 可以通过exportTemplate参数指定导出模板，默认模板为method对应的forward
		MyContext context=this.getContext(invocation);
        if ("true".equals(context.getParameter(MyStatics.PARAM_EXPORT_TO_XLS))) {
            String tmplateFile = context.getParameter(MyStatics.PARAM_EXPORT_XLS_FILE_NAME);
            if ((tmplateFile==null || tmplateFile.equals("")) && finalLocation!=null) {
                tmplateFile = finalLocation;
                tmplateFile = tmplateFile.replaceAll("\\.(jsp|JSP)", ".xls");
            }
            exportExcel(context, invocation.getAction(), ServletActionContext.getResponse(), tmplateFile);
        } else{
			if(jsonResult==null){
				jsonResult=new JSONResultHandle();
			}
			Object resultVal=invocation.getStack().findValue(MyStatics.ACTION_RESULT_VAL);
			jsonResult.execute(ServletActionContext.getResponse(), resultVal);
        }
	}
	
	/**
	 * 展现结果转换的拦截器后处理
	 * @param invocation
	 * @author:詹保山
	 */
	private void afterInterceptor(ActionInvocation invocation){
		Object action=invocation.getAction();
		if(action instanceof Struts2BaseAction){
			Object result=invocation.getStack().findValue(MyStatics.ACTION_RESULT_VAL);
			Struts2BaseAction baseAction=(Struts2BaseAction)action;
			MyInterceptorStack interceptorStack=baseAction.getInterceptorStack();
		   if(interceptorStack!=null){
			   interceptorStack.after(baseAction.getContext(),(MyAction) action, result);
		   }
		}
	}
	/**
	 * 按页面的形式输出
	 * @param finalLocation
	 * @param invocation
	 * @author:詹保山
	 */
	private void doPageExecute(String finalLocation, ActionInvocation invocation){
		//返回值是字符串，并且值要分不包含redirect:和不包含redirect:的2种情况
		Object viewType=ServletActionContext.getRequest().getAttribute(MyStatics.ACTION_VIEW_TYPE);
		Class returnType=(Class)invocation.getStack().findValue(MyStatics.ACTION_RESULT_TYPE);
		String resultVal="";	
		if(returnType==void.class){
			resultVal="";
		}else{
			resultVal=invocation.getStack().findValue(MyStatics.ACTION_RESULT_VAL).toString();
		}
		//后拦截器处理-自定义的拦截器
		this.afterInterceptor(invocation);
		 
		MyContext context=this.getContext(invocation);
		//判断展现类型，默认是JSP
		if(viewType==null){
			//判断界面是否是XLS类型
		    if (finalLocation!=null && finalLocation.matches(".*\\.(xls|XLS)")) {
	    	    exportExcel(context, invocation.getAction(), ServletActionContext.getResponse(), finalLocation);
	            return ;
		    }
			if(finalLocation!=null && "true".equals(context.getParameter(MyStatics.PARAM_EXPORT_TO_XLS))){
				finalLocation = finalLocation.replaceAll("\\.(jsp|JSP)", ".xls");
	            exportExcel(context, invocation.getAction(), ServletActionContext.getResponse(), finalLocation);
	            return ;
			}else{
				 try {
					 //不包含 redirect:的情况下
					 if(resultVal.indexOf(MyStatics.REDIRECT_ACTION_RESULT_PREFIX)!=0){
					    //进行参数的转换
						 super.doExecute(finalLocation, invocation);
					    
					 }else{//包含redirect:的情况下
						String resultUrl= resultVal.substring(9);
						this.doRedirectExecute(resultUrl, invocation);
					 }
				 } catch (Exception e) {
					e.printStackTrace();
				}
		}
		}
	}
	public void doExecute(String finalLocation, ActionInvocation invocation)
			throws Exception {
		//获取返回值类型
		Class returnType=(Class)invocation.getStack().findValue(MyStatics.ACTION_RESULT_TYPE);
		Object resultVal=invocation.getStack().findValue(MyStatics.ACTION_RESULT_VAL);
		if(returnType ==void.class){
			String actionName=invocation.getProxy().getActionName();
			String method=invocation.getProxy().getMethod();
			finalLocation=PagePathUtils.accessTypeBJspPagePath(invocation.getAction().getClass(), actionName, method);
			this.doPageExecute(finalLocation, invocation);
		}else if(returnType !=String.class) {//不为字符串的为AJAX输出
			this.doAjaxExecute(finalLocation, invocation);
		}else{
			this.doPageExecute(finalLocation, invocation);
		}
	}


}
